<?php
/**
 * Various static utilities
 */
 
class Utils {
	
	/**
   * Returns a "human" number in kb/mb/gb 
   *
   * @param int $size The decimal size to convert
   * @return string: human formated number
   */
	public static function getHumanSize($size) {
		$gb = pow(1024, 3);
		$mb = pow(1024, 2);
		$kb = pow(1024, 1);
		if ($size > $gb) {
			$humanSize = number_format($size / $gb, 2, ".", ",") . " GB";
		} elseif ($size >= $mb) {
			$humanSize = number_format($size / $mb, 2, ".", ",") . " MB";
		} elseif ($size >= $kb) {
			$humanSize = number_format($size / $kb, 2, ".", ",") . " KB";
		} else {
			$humanSize = number_format($size, 2, ".", ",") . " B";
		}
		return $humanSize;
	}
	
	public static function getHumanTime($seconds) {
		$future = new DateTime (round(time() + $seconds));
		$interval = $future->diff(new DateTime());
		$return["days"] = $interval->format("%d");
		$return["hours"] = $interval->format("%h");
		$return["minutes"] = $interval->format("%i");
		$return["seconds"] = $interval->format("%s");
		return $return;
	}
	
	/**
   * Removed a specified element from an array and re-orders keys 
   *
   * @param array $targetArray Array from which to remove element
	* @param int $element Element number to remove from array
   * @return array: re-ordered array, less element requested for removal
   */
	public static function array_delete_element($targetArray, $element) {
		if (!is_array($targetArray)) {
			throw new Exception ();
		}
		if (!is_numeric($element)) {
			throw new Exception ();
		}
		unset($targetArray[$element]);
		return array_values($targetArray);
	}
	
	public static function charLast($str) {
		return substr($str, -1);
	}
	
	public static function charStripFirst($str) {
		return substr($str, 1);
	}
	
	public static function charStripFirstTwo($str) {
		return substr($str, 2);
	}
	
	public static function charStripLast($str) {
		return substr($str, 0, -1);
	}
	
	/**
   * Processes options 
   *
   * @param array $argv Argv from the CLI
   * @param array $shortOptions Array of short options
   * @param array $longOptions Array of long options
   * @return array: processed opts
   */
	public static function getopts($argv, $shortOptions, $longOptions) {
		$options = null;
		
		$shortFlags = null;
		$shortArgs = null;
		$longFlags = null;
		$longArgs = null;
		
		foreach ($shortOptions as $shortOption) {
			if (Utils::charLast($shortOption) == ":") {
				$shortArgs[] = Utils::charStripLast($shortOption);
			} else {
				$shortFlags[] = $shortOption;
			}
		}
		
		foreach ($longOptions as $longOption) {
			if (Utils::charLast($longOption) == ":") {
				$longArgs[] = Utils::charStripLast($longOption);
			} else {
				$longFlags[] = $longOption;
			}
		}
				
		$cmd = null;
		for ($i = 0; $i < count($argv); $i++) {
			if ($i == 0) {
				$cmd = $argv[$i];
				continue;
			} 
			$opt = $argv[$i];
			if ($opt{1} == "-") {
				// long option
				$opt = Utils::charStripFirstTwo($opt);
				if (is_array($longFlags) && in_array($opt, $longFlags)) {
					$options["opts"][$opt] = null;
					continue;
				} elseif (is_array($longArgs) && in_array($opt, $longArgs)) {
					if (!isset($argv[$i+1]{0}) || $argv[$i+1]{0} == "-") {
						throw new Exception (Errors::CLIOpts_MESG_BAD_LONG_NO_ARG . " ($opt)", Errors::CLIOpts_CODE_BAD_LONG_NO_ARG);
					}
					$options["opts"][$opt] = $argv[++$i];
					continue;
				} else {
					throw new Exception (Errors::CLIOpts_MESG_BAD_LONG . " ($opt)", Errors::CLIOpts_CODE_BAD_LONG);
				}
			} elseif ($opt{0} == "-") {
				// short option
				$opt = Utils::charStripFirst($opt);				
				if (is_array($shortFlags) && in_array($opt, $shortFlags)) {
					$options["opts"][$opt] = null;
					continue;
				} elseif (is_array($shortArgs) && in_array($opt, $shortArgs)) {
					if (!isset($argv[$i+1]{0}) || $argv[$i+1]{0} == "-") {
						throw new Exception (Errors::CLIOpts_MESG_BAD_SHORT_NO_ARG . " ($opt)", Errors::CLIOpts_CODE_BAD_SHORT_NO_ARG);
					}
					$options["opts"][$opt] = $argv[++$i];
					continue;
				} else {
					throw new Exception (Errors::CLIOpts_MESG_BAD_SHORT . " ($opt)", Errors::CLIOpts_CODE_BAD_SHORT);
				} 
			} else {
				// non-opt arg
				$options["args"][] = $opt;
			}
		}
		return $options;
	}
	
	public static function getHostnameHash() {
		return hash("sha256", gethostname());
	}
	
	public static function sha256($str) {
		return hash("sha256", $str);
	}
	
	public static function array_xor($array_a, $array_b) {
		$union = array_merge($array_a, $array_b);
		$intersect = array_intersect($array_a, $array_b);
		return array_diff($union, $intersect);
	}
}
?>